﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace dllLink
{
    internal class VasicekEmpiricalEstimator : VasicekEstimator
    {
        private string mvName;
        public VasicekEmpiricalEstimator(string theName, DateTime thePricingDate, TimeSpan theHistoryDepth)
        {
            mvName = theName;
            mvPricingDate = thePricingDate;
            mvHistoryDepth = theHistoryDepth;
        }


        // retourne un tableau de taille 3 contenant les estimations des
        // 3 paramètres du modèle de Vasicek (a, b et sigma : drt = a(b-rt)dt +sigma*dWt)
        public override double[] mComputeParams()
        {
            double[] myRes = new double[3];
            double[] myData;

            double myB = 0.0; //moyenne empirique
            double myRx = 0.0;
            double myRy = 0.0;
            double myRxx = 0.0;
            double myRyy = 0.0;
            double myRxy = 0.0;
            
            double myVar = 0.0; //variance emprique
            
            double myLag = Model.mvDt; //pas de temps entre deux données, 1 jour

            // on récupère les données de taux
            myData = Cotation(mvName, mvPricingDate, mvHistoryDepth);
            int myDepth = myData.Length;
            
            for(int i=1;i<myDepth;i++)
            {
                myRx += myData[i-1];
                myRxx += myData[i-1]*myData[i-1];

                myRy += myData[i];
                myRyy += myData[i]*myData[i];

                myRxy += myData[i - 1] * myData[i]; 
            }
            
            //moyenne empirique de tout l'échantillon
            myB = (myRx + myData[myDepth - 1]) / myDepth;
            myDepth -= 1;
            //Variance empirique de tout l'échantillon
            myVar = myRxx + myData[myDepth] * myData[myDepth] / myDepth;
            myVar -= myB * myB;
            //variance empirique de l'echantillon allant de 0 à n-2 (taille n-1)
            myRxx /= myDepth;
            myRxx -= (myRx / myDepth) * (myRx / myDepth);
            //variance empirique de l'echantillon allant de 1 à n-1 (taille n-1)
            myRyy /= myDepth;
            myRyy -= (myRy / myDepth) * (myRy / myDepth);
            //variance empirique de l'echantillon allant de 0 à n-2 et celui allant de 1 à n-1
            myRxy /= myDepth;
            myRxy -= myRy * myRx / (myDepth * myDepth);

            //b sous Q
            myRes[1] = myB;
            
            double myTmp, mySd, myA;
            myA = myRxy / myRxx;
            myTmp = 1 - (myRxy * myRxy / (myRxx * myRyy));
            mySd = Math.Sqrt(myDepth*myRyy*myTmp/(myDepth-2));
            //sigma sous P 
            myRes[2] = mySd * Math.Sqrt(-2 * Math.Log(myA) / myLag / (1 - myA*myA));
            //a sous P
            myRes[0] = myRes[2] * myRes[2] / (2.0 * myVar);

            return myRes;
        }
    }
}

